package com.snowy.framework.wechatAuth.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.snowy.framework.exception.UABPException;
import com.snowy.framework.util.OkHttpUtils;
import com.snowy.framework.wechatAuth.dto.req.WechatAppletAuthReq;
import com.snowy.framework.wechatAuth.dto.resp.WechatUserInfo;
import com.snowy.framework.wechatAuth.enums.WechatErroEnum;
import com.snowy.framework.wechatAuth.service.WechatAppletService;
import com.snowy.framework.wechatAuth.util.AssertUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

/**
 * @author hjl
 */
@Slf4j
@Service("wechatAppletService")
public class WechatAppletServiceImpl implements WechatAppletService {

    public static String WECHAT_OPENDID_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
    /**
     * 小程序登录取access_token  URL
     */
    private static String WECHAT_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";


    @Override
    public String getAppletOpenId(WechatAppletAuthReq wechatAppletAuthReq) {
        String appId = wechatAppletAuthReq.getAppId();
        String appSecret = wechatAppletAuthReq.getAppSecret();

        //判断是否配置小程序参数
        if(StrUtil.hasBlank(appId,appSecret)){
            throw new UABPException(WechatErroEnum.NO_APPINFO_ERROR);
        }

        //调用小程序登录接口获取信息
        String accessTokenUrl = String.format(WECHAT_OPENDID_URL, appId, appSecret, wechatAppletAuthReq.getCode());
        String respStr = null;
        try {
            respStr = OkHttpUtils.httpGet(accessTokenUrl);
        } catch (Exception e) {
            log.error("==getAppletOpenId==",e);
        }

        //判断微信是否返回消息
        if(StrUtil.isBlank(respStr)){
            throw new UABPException(WechatErroEnum.INTF_ERROR);
        }

        //取微信返回错误信息
        JSONObject jsonObject = JSONObject.parseObject(respStr);
        log.error("==jsonObject=="+jsonObject);

        if(ObjectUtil.isNotEmpty(jsonObject.getInteger("errcode"))){
            throw new UABPException(jsonObject.getString("errcode"),jsonObject.getString("errmsg"));
        }

        //取返回openId
        String openId = jsonObject.getString("openid");
        if(StrUtil.isBlank(openId)){
            throw new UABPException(WechatErroEnum.INTF_ERROR);
        }
        return openId;
    }
    /**
     * @param code 授权码
     * @return
     */
    @Override
    public WechatUserInfo getWechatUserInfo(String code, String appId, String appKey) {
        if (StringUtils.isBlank(appId) || StringUtils.isBlank(appKey)) {
            throw new UABPException(WechatErroEnum.NO_APPINFO_ERROR);
        }
        //2、获取微信认证信息accessToken、openId
        JSONObject jsonObject = this.getAuthInfo(code, appId, appKey);
        String accessToken = jsonObject.getString("access_token");
        String openId = jsonObject.getString("openid");
        //3、取微信用户信息
        WechatUserInfo wechatUserInfo = new WechatUserInfo();
        wechatUserInfo.setOpenId(openId);
        wechatUserInfo.setAccessToken(accessToken);
        return wechatUserInfo;
    }

    /**
     * 取微信认证信息
     *
     * @param code
     * @param appId
     * @param appKey
     * @return
     */
    private JSONObject getAuthInfo(String code, String appId, String appKey) {
        //1、http调用接口获取微信认证信息
        String accessOpenIdUrl = String.format(WECHAT_OPENDID_URL, appId, appKey, code);
        String authStr = null;
        try {
            authStr = OkHttpUtils.httpGet(accessOpenIdUrl);
        } catch (Exception e) {
            log.error("==getAuthInfo1==" + e.getMessage());
            throw new UABPException(WechatErroEnum.INTF_ERROR);
        }
        if (StringUtils.isEmpty(authStr)) {
            throw new UABPException(WechatErroEnum.INTF_ERROR);
        }
        log.info("获取微信opendID返回内容：{}", authStr);
        //2、返回字符串转换为JSONObject
        JSONObject authJsonObject;
        try {
            authJsonObject = JSONObject.parseObject(authStr);
        } catch (Exception e) {
            log.error("==getAuthInfo2==" + e.getMessage());
            throw new UABPException(WechatErroEnum.JSON_ANALYSIS_ERROR);
        }
        //3、解析authJsonObject获取token、openId
        //AssertUtil.hasText(authJsonObject.getString("access_token"), WechatErroEnum.NO_WECHAT_ASSTOKEN);
        AssertUtil.hasText(authJsonObject.getString("openid"), WechatErroEnum.NO_WECHAT_OPEN_ID);

        //获取 access_token
        String accessTokenUrl = String.format(WECHAT_ACCESS_TOKEN_URL, appId, appKey);
        String authToken = null;
        try {
            authToken = OkHttpUtils.httpGet(accessTokenUrl);
        } catch (Exception e) {
            log.error("==authToken==" + e.getMessage());
            throw new UABPException(WechatErroEnum.INTF_ERROR);
        }
        if (StringUtils.isEmpty(authToken)) {
            throw new UABPException(WechatErroEnum.INTF_ERROR);
        }
        log.info("获取微信accessToken返回内容：{}", authStr);

        JSONObject tokenJsonObject;
        try {
            tokenJsonObject = JSONObject.parseObject(authToken);
        } catch (Exception e) {
            log.error("==getAuthInfo2==" + e.getMessage());
            throw new UABPException(WechatErroEnum.JSON_ANALYSIS_ERROR);
        }

        AssertUtil.hasText(tokenJsonObject.getString("access_token"), WechatErroEnum.NO_WECHAT_ASSTOKEN);
        authJsonObject.put("access_token", tokenJsonObject.getString("access_token"));


        return authJsonObject;
    }
}
